﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xml;
using System.IO;
using System.Security;
using System.Windows.Media;

namespace PasswordProvider.View.Library
{
    /// <summary>
    /// A password box that allows binding on the password value.
    /// </summary>
    public partial class BindablePasswordBox : UserControl
    {
        public BindablePasswordBox()
        {
            InitializeComponent();            
        }


        #region Overrides

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            PasswordBox.PasswordChanged +=
                delegate
                {
                    SecurePassword = PasswordBox.SecurePassword;
                };            
        }

        protected override void OnGotFocus(RoutedEventArgs e)
        {
            base.OnGotFocus(e);
            
            if (PasswordBox != null)
                PasswordBox.Focus();
                
        }
        
        #endregion

        #region Dependency Properties

        /// <summary>
        /// Override default border thickness behavior, so there is a thickness of 1 unless explicitly 
        /// set otherwise.
        /// </summary>
        public static readonly new DependencyProperty BorderThicknessProperty =
            Control.BorderThicknessProperty.AddOwner(typeof(BindablePasswordBox),
            new FrameworkPropertyMetadata(new Thickness(1)));

        /// <summary>
        /// Override default behavior for background property. (Don't want to inherit background from the parent of UserControl
        /// But still allow explicitly set background. 
        /// </summary>
        public static readonly new DependencyProperty BackgroundProperty =
            Control.BackgroundProperty.AddOwner(typeof(BindablePasswordBox),
            new FrameworkPropertyMetadata(SystemColors.WindowBrush));

        /// <summary>
        /// Foreground, to override default inheritance behavior.
        /// </summary> // (Note: Using AddOwner as above for background doesn't work with foreground, don't know why.)
        public static readonly new DependencyProperty ForegroundProperty =
            DependencyProperty.Register("Foreground", typeof(Brush), typeof(BindablePasswordBox),
                new FrameworkPropertyMetadata(SystemColors.WindowTextBrush));
        /// <summary>
        /// Get or set Foreground. 
        /// </summary> // Note: Needed here so values get set, since using DependencyProperty.Register, probably.
        public new Brush Foreground
        {
            get { return (Brush)GetValue(ForegroundProperty); }
            set { SetValue(ForegroundProperty, value); }
        }

        /// <summary>
        /// Bind to the password.
        /// </summary>
        public static readonly DependencyProperty SecurePasswordProperty =
          DependencyProperty.Register("SecurePassword", typeof(SecureString), typeof(BindablePasswordBox));

        /// <summary>
        /// Get or set the password value.
        /// </summary>
        public SecureString SecurePassword
        {
            get
            {
                return (SecureString)GetValue(SecurePasswordProperty);
            }
            set
            {
                SetValue(SecurePasswordProperty, value);
            }
        }

        #endregion

        #region Private Helpers

        private PasswordBox PasswordBox
        {
            get
            {
                if (_passwordBox == null)
                {
                    _passwordBox = FindPasswordBox();
                }
                return _passwordBox;
            }
        } PasswordBox _passwordBox;

        /// <summary>
        /// Recursively search the visual children of the control, looking for an instance of PasswordBox. 
        /// An alternative to using FindResource, just for fun.
        /// </summary>
        private PasswordBox FindPasswordBox()
        {
            if(VisualTreeHelper.GetChildrenCount(this) > 0)
            {
                return FindPasswordBox(VisualTreeHelper.GetChild(this, 0));
            }
            return null;
        }
        private PasswordBox FindPasswordBox(DependencyObject root)
        {
            PasswordBox passwordBox = root as PasswordBox;
            if (passwordBox != null)
                return passwordBox;

            for (int x = 0; x < VisualTreeHelper.GetChildrenCount(root); x++)
            {
                FindPasswordBox(VisualTreeHelper.GetChild(root, x));
            }

            return null;
        }

        #endregion // Private Helpers

    }
}
